﻿using AutoMapper;
using HamcoWcs.Contract.ContractCommon;
using HamcoWcs.Contract.ContractForeEnd;
using HamcoWcs.DAL;
using HamcoWcs.Entitys.RoleMenus;
using HamcoWcs.Entitys.UserInfos;
using HamcoWcs.Main.SingalRFiles;
using HamcoWcs.Models.Common;
using HamcoWcs.Models.Exceptions;
using HamcoWcs.Models.ForeEndModels.LoginInfos;
using HamcoWcs.Models.ForeEndModels.MenuInfos;
using HamcoWcs.Models.ForeEndModels.RoleInfos;
using HamcoWcs.Models.ForeEndModels.UserInfos;
using HamcoWcs.Service.Common.SingalRs;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace HamcoWcs.Main.Controllers.Manage
{
    /// <summary>
    /// 前端管理接口
    /// </summary>
    [ApiController]
    //[ApiExplorerSettings(IgnoreApi = true)]
    [Route("[controller]")]
    public class ManageController : BasicController
    {
        #region [Constructor]
        private readonly IHubContext<PushHub> _hubContext;
        private readonly IHubContext<MonitorHub> _monitorContext;

        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IManageService _manageService;

        /// <summary>
        /// 
        /// </summary>
        public override string ControllerName => "ManageController";

        /// <summary>
        /// ct
        /// </summary>
        public ManageController(IHubContext<MonitorHub> monitorHub, IHubContext<PushHub> hubContext, WcsDbContext wcsDbContext, IMapper mapper, ILoggerService logger, IHttpContextAccessor httpContextAccessor,
            IManageService manageService)
            : base(logger, mapper, wcsDbContext)
        {
            _manageService = manageService;
            _httpContextAccessor = httpContextAccessor;
            _hubContext = hubContext;
            _monitorContext = monitorHub;
        }

        #endregion Constructor

        #region [Login]

        /// <summary>
        /// 前端获取Ip
        /// </summary>
        /// <returns></returns>
        [HttpPost(nameof(GetHost))]
        public IActionResult GetHost()
        {
            try
            {
                var ip = _httpContextAccessor.HttpContext.Connection.RemoteIpAddress.ToString();
                return Json(new ForeEndResult() { Details = ip });
            }
            catch (Exception ex)
            {
                AddSystemLog(ex.Message);
                return QueryFailureResult();
            }

        }

        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="loginInfo">登录信息</param>
        /// <returns>code:200 => success</returns>
        [HttpPost(nameof(Login))]
        public async Task<IActionResult> Login(LoginInfo loginInfo)
        {
            try
            {
                string ip = "";
                try
                {
                    ip = _httpContextAccessor.HttpContext.Connection.RemoteIpAddress.ToString();
                }
                catch (Exception ex)
                {
                    AddSystemLog("获取Ip失败");
                }
                string pattern = @"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\da-zA-Z]).{8,}$";

                bool isValid = Regex.IsMatch(loginInfo.Password, pattern);

                if (!isValid)
                {
                    return Json(ForeEndResult.Fail("密码不符合要求，请联系管理员修改密码"));
                }

                var result = _manageService.Login(loginInfo);


                if (result.Code == 200)
                {
                    _logger.InsertLoginLog(loginInfo.UserName, ip);
                    var u = _wcsDbContext.Set<LoginStatus>().FirstOrDefault(x => x.UserNo == result.UserNo);
                    if (u != null)
                    {
                        if (u.IsOnline == true)
                        {
                            u.Desc = "您已在其他地方登录";
                            await _monitorContext.Clients.All.SendAsync("LoginStatusSame", u);
                        }

                        u.Token = result.Token;
                        u.IsOnline = true;
                        u.CreatedTime = DateTime.Now;
                    }
                    else
                    {
                        _wcsDbContext.Set<LoginStatus>().Add(new LoginStatus()
                        {
                            Ip = ip,
                            UserName = result.UserName,
                            UserNo = result.UserNo,
                            IsOnline = true,
                            Operate = 0,
                            Token = result.Token
                        });
                    }
                    _wcsDbContext.SaveChanges();
                }
                return Json(result);
            }
            catch (Exception ex)
            {
                AddSystemLog(ex.Message);
                return Json(ForeEndResult.Fail("Unknown exception"));
            }
        }


        /// <summary>
        /// 登出
        /// </summary>
        /// <param name="loginInfo">登录信息</param>
        /// <returns>code:200 => success</returns>
        [HttpPost(nameof(Logout))]
        public IActionResult Logout([FromHeader] string userName)
        {
            try
            {
                try
                {
                    var u = _wcsDbContext.Set<LoginStatus>().FirstOrDefault(x => x.UserNo == userName);
                    if (u != null) u.IsOnline = false;
                    _wcsDbContext.SaveChanges();
                }
                catch (Exception)
                {

                }
                return Json(ForeEndResult.Ok);
            }
            catch (Exception ex)
            {
                AddSystemLog(ex.Message);
                return Json(ForeEndResult.Fail("Unknown exception"));
            }
        }


        /// <summary>
        /// 指定登出
        /// </summary>
        [HttpPost(nameof(LogoutF))]
        public async Task<IActionResult> LogoutF(LogoutInfo model, [FromHeader] string userName)
        {
            try
            {
                if (string.IsNullOrEmpty(model.UserNo)) throw new WarningException("用户账号不得为空");
                var u = _wcsDbContext.Set<LoginStatus>().FirstOrDefault(x => x.UserNo == model.UserNo)
                    ?? throw new WarningException("未找到该用户的登录信息");
                if (!u.IsOnline) throw new WarningException("该用户已离线");

                u.Desc = "管理员断开了您的连接";
                //await _hubContext.Clients.All.SendAsync("LoginStatus", u);
                await _monitorContext.Clients.All.SendAsync("LoginStatus", u);
                AddOperationLog(userName, $"使{u.UserName}-{u.UserNo}离线");
                return Json(ForeEndResult.Ok);
            }
            catch (WarningException ex)
            {
                return Warning(ex);
            }
            catch (Exception ex)
            {
                AddSystemLog(ex.Message);
                return Json(ForeEndResult.Fail("Unknown exception"));
            }
        }

        /// <summary>
        /// 获取登录的用户
        /// </summary>
        [HttpPost(nameof(GetOnlineUsers))]
        public IActionResult GetOnlineUsers()
        {
            try
            {
                var users = _wcsDbContext.Set<LoginStatus>()
                    .AsNoTracking()
                    .Where(x => x.IsOnline)
                    .ToList();

                return Json(new ForeEndResult(users));
            }
            catch (WarningException ex)
            {
                return Warning(ex);
            }
            catch (Exception ex)
            {
                AddSystemLog(ex.Message);
                return Json(ForeEndResult.Fail("Unknown exception"));
            }
        }

        #endregion Login

        #region User

        /// <summary>
        /// 添加用户
        /// </summary>
        /// <param name="userInfoDto"></param>
        /// <returns>code:200 => success</returns>
        [HttpPost(nameof(AddUser))]
        public IActionResult AddUser(UserInfoDto userInfoDto, [FromHeader] string userName)
        {
            try
            {
                string pattern = @"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\da-zA-Z]).{8,}$";

                bool isValid = Regex.IsMatch(userInfoDto.Password, pattern);

                if (!isValid)
                {
                    return Json(ForeEndResult.Fail("密码不符合要求，请按照策略：大小写、数字特殊字符、8位以上"));
                }
                var isAdd = _manageService.AddUser(userInfoDto);
                if (!isAdd) throw new Exception("添加用户时数据库异常");

                var msg = _manageService.Serialize(userInfoDto);
                AddOperationLog(userName, msg);
                return Json(ForeEndResult.Ok);
            }
            catch (Exception ex)
            {
                AddSystemLog(ex.Message);
                return CreateFailureResult();
            }

        }

        /// <summary>
        /// 按Id删除用户
        /// </summary>
        /// <param name="deleteUserInfos"></param>
        /// <returns></returns>
        [HttpPost(nameof(DeleteUser))]
        public IActionResult DeleteUser(List<DeleteUserInfo> deleteUserInfos, [FromHeader] string userName)
        {
            try
            {
                var isDelete = _manageService.DeleteUser(deleteUserInfos);
                if (!isDelete) throw new Exception("删除失败，数据库异常");
                //_manageService.AddOperationLog(userName, $"删除ID[{string.Join(',', deleteUserInfos.Select(d => d.Id))}]");

                var msg = $"删除ID[{string.Join(',', deleteUserInfos.Select(d => d.Id))}]";
                AddOperationLog(userName, msg);
                return Json(ForeEndResult.Ok);
            }
            catch (Exception ex)
            {
                AddSystemLog(ex.Message);
                return DeleteFailureResult();
            }

        }

        /// <summary>
        /// 分页查询用户
        /// </summary>
        /// <param name="queryUserInfo"></param>
        /// <returns></returns>
        [HttpPost(nameof(QueryUser))]
        public IActionResult QueryUser(QueryUserInfo queryUserInfo)
        {
            try
            {
                var result = _manageService.QueryUser(queryUserInfo);
                return Json(result);
            }
            catch (Exception ex)
            {
                AddSystemLog(ex.Message);
                return QueryFailureResult();
            }
        }

        /// <summary>
        /// 更新用户
        /// </summary>
        /// <param name="userInfoDto"></param>
        /// <returns></returns>
        [HttpPost(nameof(UpdateUser))]
        public IActionResult UpdateUser(UserInfoDto userInfoDto, [FromHeader] string userName)
        {
            try
            {
                string pattern = @"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\da-zA-Z]).{8,}$";

                bool isValid = Regex.IsMatch(userInfoDto.Password, pattern);

                if (!isValid)
                {
                    return Json(ForeEndResult.Fail("密码不符合要求，请按照策略：大小写、数字特殊字符、8位以上"));
                }
                var isUpdate = _manageService.UpdateUser(userInfoDto);
                if (!isUpdate) throw new Exception("");

                var msg = _manageService.Serialize(userInfoDto);
                AddOperationLog(userName, msg);
                //_manageService.AddOperationLog(userName, _manageService.Serialize(userInfoDto)); 
                return Json(ForeEndResult.Ok);
            }
            catch (Exception ex)
            {
                AddSystemLog(ex.Message);
                return UpdateFailureResult();
            }

        }

        #endregion User

        #region Role

        /// <summary>
        /// 为角色添加菜单
        /// </summary>
        /// <returns></returns>
        [HttpPost(nameof(AddRoleMenu))]
        public IActionResult AddRoleMenu(RoleMenu roleMenu, [FromHeader] string userName)
        {
            try
            {
                _manageService.AddRoleMenu(roleMenu);

                return Json(ForeEndResult.Ok);
            }
            catch (Exception ex)
            {
                return ErrorHandle("为角色添加菜单失败", ex);
            }
            finally
            {
                AddOperationLog(userName, "为角色添加菜单");
            }
        }

        /// <summary>
        /// 创建角色
        /// </summary>
        [HttpPost(nameof(CreateRole))]
        public IActionResult CreateRole(RoleInfoDto roleInfoDto, [FromHeader] string userName)
        {
            try
            {
                var result = _manageService.AddRole(roleInfoDto);
                if (!result) throw new Exception();

                AddOperationLog(userName, "创建角色");
                return Json(ForeEndResult.Ok);
            }
            catch (Exception ex)
            {
                AddSystemLog(ex.Message);
                return CreateFailureResult();
            }

        }

        /// <summary>
        /// 删除角色
        /// </summary>
        [HttpPost(nameof(DeleteRole))]
        public IActionResult DeleteRole(List<long> roleIdList, [FromHeader] string userName)
        {
            try
            {
                var result = _manageService.DeleteRole(roleIdList);
                if (!result) throw new Exception("删除角色，数据库异常");

                AddOperationLog(userName, $"删除角色 => {string.Join("|", roleIdList)}");
                return Json(ForeEndResult.Ok);
            }
            catch (Exception ex)
            {
                AddSystemLog(ex.Message);
                return DeleteFailureResult();
            }
        }

        /// <summary>
        /// 删除角色-菜单
        /// </summary>
        [HttpPost(nameof(DeleteRoleMenu))]
        public IActionResult DeleteRoleMenu(RoleMenu roleMenu, [FromHeader] string userName)
        {
            try
            {
                return Ok();
            }
            catch (Exception ex)
            {
                AddSystemLog(ex.Message);
                return DeleteFailureResult();
            }
        }

        /// <summary>
        /// 查询角色
        /// </summary>
        /// <param name="queryRoleInfo"></param>
        /// <param name="userName"></param>
        /// <returns></returns>
        [HttpPost(nameof(QueryRole))]
        public IActionResult QueryRole(QueryRoleInfo queryRoleInfo, [FromHeader] string userName)
        {
            try
            {
                var result = _manageService.QueryRole(queryRoleInfo);
                AddOperationLog(userName, "为角色添加菜单");
                return Json(result);
            }
            catch (Exception ex)
            {
                AddSystemLog(ex.Message);
                return QueryFailureResult();
            }
        }

        /// <summary>
        /// 更改角色
        /// </summary>
        [HttpPost(nameof(UpdateRole))]
        public IActionResult UpdateRole(RoleInfoDto roleInfoDto, [FromHeader] string userName)
        {
            try
            {
                var result = _manageService.UpdateRole(roleInfoDto);
                if (!result) throw new Exception();

                AddOperationLog(userName, $"{_manageService.Serialize(roleInfoDto)}");
                return Json(ForeEndResult.Ok);
            }
            catch (Exception ex)
            {
                AddSystemLog(ex.Message);
                return UpdateFailureResult();
            }
        }

        #endregion Role

        #region Menu

        /// <summary>
        /// 创建菜单
        /// </summary>
        /// <returns></returns>
        [HttpPost(nameof(CreateMenu))]
        public IActionResult CreateMenu(MenuInfoDto menuInfoDto, [FromHeader] string userName)
        {
            try
            {
                var flag = _manageService.AddMenu(menuInfoDto);
                if (!flag) throw new Exception();
                return Json(ForeEndResult.Ok);
            }
            catch (Exception ex)
            {
                AddSystemLog(ex.Message);

                return ErrorHandle("创建菜单失败", ex);
            }
            finally
            {
                AddOperationLog(userName, "创建菜单信息");
            }
        }

        /// <summary>
        /// 删除菜单
        /// </summary>
        /// <param name="deleteIdList"></param>
        /// <param name="userName"></param>
        /// <returns></returns>
        [HttpPost(nameof(DeleteMenu))]
        public IActionResult DeleteMenu(List<long> deleteIdList, [FromHeader] string userName)
        {
            try
            {
                var isDelete = _manageService.DeleteMenu(deleteIdList);
                if (!isDelete) throw new Exception();
                return Json(ForeEndResult.Ok);
            }
            catch (Exception ex)
            {
                return ErrorHandle("删除菜单失败", ex);
            }
            finally
            {
                AddOperationLog(userName, $"删除菜单:{string.Join("|", deleteIdList)}");
            }
        }

        /// <summary>
        /// 查询菜单
        /// </summary>
        /// <returns></returns>
        [HttpPost(nameof(QueryMenu))]
        public IActionResult QueryMenu()
        {
            try
            {
                var result = _manageService.QueryMenu();
                return Json(result);
            }
            catch (Exception ex)
            {
                return ErrorHandle("查询菜单失败", ex);
            }
        }

        /// <summary>
        /// 更新菜单
        /// </summary>
        /// <returns></returns>
        [HttpPost(nameof(UpdateMenu))]
        public IActionResult UpdateMenu(MenuInfoDto menuInfoDto, [FromHeader] string userName)
        {
            try
            {
                var isUpdate = _manageService.UpdateMenu(menuInfoDto);
                if (!isUpdate) throw new Exception();
                return Json(ForeEndResult.Ok);
            }
            catch (Exception ex)
            {
                return ErrorHandle("更新菜单失败", ex);
            }
            finally
            {
                AddOperationLog(userName, $"更新菜单");
            }
        }

        #endregion Menu

        #region Methods

        //private void AddOperationLog(string userName, string msg, [CallerMemberName] string methodName = "")
        //{
        //    _logger.AddOperationLog(userName, "ForeEnd", methodName, msg);
        //}

        private IActionResult ErrorHandle(string errMsg, Exception ex = null)
        {
            if (ex != null) errMsg += $" => {ex.Message}";
            _logger.AddSystemErrorLog("ManageController:" + errMsg);
            return Json(ForeEndResult.Fail(errMsg));
        }

        #endregion Methods


    }
}